package com.ruoyi.act.module.service.impl;

import com.ruoyi.act.module.domain.ActBizInfo;
import com.ruoyi.act.module.service.IJJwtService;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.StringUtils;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service("ijJwtService")
public class JJwtServiceImpl implements IJJwtService {

    @Autowired
    private RedisCache redisCache;

    @Value("${tenant.header}")
    private String header;

    @Value("${tenant.secretKey}")
    private String secretKey;

    @Value("${tenant.expireTime}")
    private Integer expireTime;

    public static final String TENANT_KEY = "tenant_key";

    protected static final long MILLIS_SECOND = 1000;

    protected static final long MILLIS_MINUTE = 60 * MILLIS_SECOND;

    private static final Long MILLIS_MINUTE_TEN = 20 * 60 * 1000L;

    @Override
    public ActBizInfo getTenant(HttpServletRequest request) {
        // 获取请求携带的令牌
        String token = getToken(request);
        if (StringUtils.isNotEmpty(token)) {
            Claims claims = parseToken(token);
            if (claims == null) {
                return null;
            }
            // 解析对应的权限以及用户信息
            String id = (String) claims.get(TENANT_KEY);
            ActBizInfo actBizInfo = redisCache.getCacheObject(id);
            return actBizInfo;
        }
        return null;
    }

    @Override
    public String createToken(ActBizInfo actBizInfo) {
        refreshToken(actBizInfo);
        Map<String, Object> claims = new HashMap<>();
        claims.put(TENANT_KEY, actBizInfo.getId());
        String token = Jwts.builder()
                .setClaims(claims)
                .signWith(SignatureAlgorithm.HS512, secretKey).compact();
        return token;
    }

    @Override
    public Claims parseToken(String token) {
        try {
            return Jwts.parser()
                    .setSigningKey(secretKey)
                    .parseClaimsJws(token)
                    .getBody();
        } catch (Exception e) {
            return null;
        }

    }

    @Override
    public String getToken(HttpServletRequest request) {
        String token = request.getHeader(header);
        if (StringUtils.isNotEmpty(token) && token.startsWith(Constants.TOKEN_PREFIX)) {
            token = token.replace(Constants.TOKEN_PREFIX, "");
        }
        return token;
    }

    @Override
    public void verifyToken(ActBizInfo actBizInfo) {
        long expireTime = actBizInfo.getExpireTime();
        long currentTime = System.currentTimeMillis();
        if (expireTime - currentTime <= MILLIS_MINUTE_TEN) {
            refreshToken(actBizInfo);
        }
    }

    @Override
    public void refreshToken(ActBizInfo actBizInfo) {
        actBizInfo.setLoginTime(System.currentTimeMillis());
        actBizInfo.setExpireTime(actBizInfo.getLoginTime() + expireTime * MILLIS_MINUTE);
        redisCache.setCacheObject(actBizInfo.getId(), actBizInfo, expireTime, TimeUnit.MINUTES);
    }
}
